package club.beimeng.emailserver.service;

import club.beimeng.emailserver.entity.BEmail;
import club.beimeng.emailserver.utils.AccountDistribution;
import club.beimeng.emailserver.utils.Property;
import com.sun.mail.util.MailSSLSocketFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.security.GeneralSecurityException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class EmailService {
    Session session ; // 本地session环境
    Queue<MimeMessage> queue = new LinkedList<MimeMessage>(); // 全局队列
    boolean threadRunning = false;

    ExecutorService threadPool;

    private final static java.util.logging.Logger logger = java.util.logging.Logger.getLogger("SendTask");

    @Autowired
    AccountDistribution users;

    {// 初始化代码块
        logger.info("开始初始化 -> EmailService");
        Properties prop = new Properties();
        prop.setProperty("mail.host", "smtp.qq.com");  //设置QQ邮件服务器 smtp.exmail.qq.com
        prop.setProperty("mail.transport.protocol", "smtp");  // 邮件发送协议

        // 关于QQ邮箱，还要设置SSL加密，加上以下代码即可
        MailSSLSocketFactory sf = null;
        try {
            sf = new MailSSLSocketFactory();
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);
        session = Session.getDefaultInstance(prop);
    }



    public boolean receiveTask(BEmail bEmail){ // 接收任务函数
        logger.info("得到任务" + bEmail.getSubject());
        MimeMessage message = new MimeMessage(session); // 创建邮件对象
//        message.setFrom();// 这个将在发送邮件函数中配置
        try {
            message.setRecipients(Message.RecipientType.TO,bEmail.getInternetAddresses()); // 配置收件人
            message.setSubject(bEmail.getSubject()); // 配置标题
            message.setContent(bEmail.getMimeMultipart()); // 配置内容
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        return receiveTask(message);
    }

    public boolean receiveTask(String[] recipients, String title, String html) { // 接收任务函数
        String text = "";
        if (html.length() >= 5){
            text = html.substring(1,5);
        }else
            text = html;
        logger.info( "得到任务 - " + "接收者:[ " + Arrays.toString(recipients) + " ] 标题:[ " + title + " ] 内容:[ " + text + "...]"); // 日志输出

        MimeMessage message = new MimeMessage(session); // 创建邮件对象

        String str = Arrays.toString(recipients).replace("[","").replace("]","").replace(" ","");

        try {
            message.setSubject(title);
            message.setRecipients(Message.RecipientType.TO, str);
            message.setContent(html,"text/html;charset=UTF-8");
        } catch (MessagingException e) {
            logger.warning("请仔细检查收件人账号列表");
            e.printStackTrace();
            return false;
        }

        return receiveTask(message);
    }

    private boolean receiveTask(MimeMessage message){
        String subject = "";
        try {
             subject = message.getSubject();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        logger.info("添加任务至队列 :" + subject);


        queue.offer(message);
        if (!threadRunning){
            threadRunning = true;
            new Thread(new PlanningTask()).start();
        }

        return true;
    }


    class SolveTask implements Runnable{
        MimeMessage[] taskMessages;
        String[] sender;

        public SolveTask(MimeMessage[] taskMessages, String[] sender){ // 写下构造方法
            this.taskMessages = taskMessages;
            this.sender = sender;
        }

        @Override
        public void run() {
            for (MimeMessage taskMessage : taskMessages) { // 使用新线程发送邮件
                logger.info("加速线程动作");
                sendEmail(taskMessage,sender);
            }
        }
    }

    class PlanningTask implements Runnable{ // 规划任务线程

        @Override
        public void run() {
            threadPool = Executors.newFixedThreadPool(Property.THREADS);
            logger.info("规划线程状态 - 第一次开启");
            logger.info("创建线程池" + "长度 :" + Property.THREADS);
            while (threadRunning){
                MimeMessage message = queue.poll(); // 取出任务
                if (message == null)
                    continue;
                String subject = null;
                try {
                    subject = message.getSubject();
                } catch (MessagingException e) {
                    e.printStackTrace();
                }
                logger.info("开始处理任务" + subject);
                sendEmail(message);
                try {
                    Thread.sleep(1000); // 等待一秒钟
                    if (queue.size() > 4) {
                        logger.info("开启新的线程");
                        MimeMessage[] mimeMessages = new MimeMessage[3];
                        for (int i = 0; i < 3; i++) {
                            mimeMessages[i] = queue.poll();
                        }
                        String[] sender = users.getSender();
                        threadPool.submit(new SolveTask(mimeMessages,sender));// 将三个任务分配给新线程
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                logger.info("规划线程状态 - 运行中");
            }
        }
    }

    public boolean sendEmail(MimeMessage message,String[] sender){ // 方法重载
        return send(message,sender);
    }

    public boolean sendEmail(MimeMessage message){
        String[] sender = users.getSender();
        return send(message, sender);
    }

    public boolean send(MimeMessage message,String[] emailN){
        String subject = null;
        try {
            subject = message.getSubject();
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        logger.info("准备发送邮件任务" + subject);
        try {
            Transport ts = session.getTransport(); //通过session得到transport对象,用它装载Message(邮件本体对象)
            String emNumber = emailN[0];
            String emCode = emailN[1];

            ts.connect("smtp.qq.com",emNumber,emCode);
            String signature = "";

            logger.info("发送昵称" + Property.SIGNATURE);

            signature = javax.mail.internet.MimeUtility.encodeText(Property.SIGNATURE);

            message.setFrom(new InternetAddress(signature +" <"+ emailN[0] + ">")); // 设置签名
            ts.sendMessage(message, message.getAllRecipients()); // 发送邮件
            ts.close();
        } catch (Exception e) {
            e.printStackTrace();
            logger.warning("发送失败 位置 sendEmail" + subject);
            return false;
        }
        logger.info("邮件任务发送成功" + subject);
        return true;
    }


}
